package com.iamteer.day16;

import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Supplier;

import apple.laf.JRSUIUtils.Tree;

/**
主要回顾：Set 集合

集合体系：
--------| Collection 单列集合的根接口
------------| List	有序，可重复
----------------| ArrayList		底层维护一个 Object 数组，查询快，增删慢
----------------| LinkedList	底层使用链表实现，查询慢，增删快
----------------| Vector		底层维护一个 Object 数组，线程同步 

------------| Set	无序，不可重复
----------------| HashSet	底层使用哈希表实现，存取速度快
----------------| TreeSet	底层使用红黑树实现

Set：元序：添加元素的顺序与元素出来的顺序不一致
Set 方法与 List 方法基本一致
		
------------------------------------------------------------------------------------------------------		
1. HashSet
	1.1 原理：
		添加元素时，HashSet 会先调用元素的 hashCode 方法得到元素的哈希值，然后通过元素的哈希值经过移位等运算，算出元素的存储位置。
		如果该位置是空的，则直接把元素存储在该位置上；
		如果该位置目前已经存放了元素，则调用元素的 equals 方法判断是否同一个元素，若为同一元素，则不添加，否则添加。
	
------------------------------------------------------------------------------------------------------		
2. TreeSet（二叉树会自动调整节点）
	2.1 往TreeSet 添加元素时，若元素本身具备自然顺序特性，则按该特性进行排序存储
	2.2 往TreeSet 添加元素时，若元素本身不具备自然顺序特性，则元素所属类必须实现 Comparable 接口，把元素的比较规则定义在 compareTo(T o)方法上。
	2.3 比较元素时，若 compareTo 方法返回 0，则视为重复元素，不能添加
	2.4 往TreeSet 添加元素时，如果元素本身不具备自然顺序特性，且没实现 Comparable 接口，则必须在创建 TreeSet 时传入一个比较器。
	2.5 比较器的优先级要高于 compareTo 方法
	
	定义比较器：自定义一个类实现 Comparator 接口即可，把元素与元素之间的比较规则定义在 compare 方法内。
	
	class 类名 implements Comparator{
		代码
	}
	
	对不具备自然顺序特性的元素使用 TreeSet，有 2 种办法：
	方式一：实现 Comparable 接口的 compareTo 方法；
	方式二：定义一个类实现Comparator接口的 compare 方法；（优先级高，推荐使用）
	
 */
class Human{
	int id;
	String name;
	public Human(int id, String name) {
		this.id = id;
		this.name = name;
	}	
	
	@Override
	public String toString() {
		return "{ 编号：" + this.id + " 姓名：" + this.name + "}";
	}
	
	@Override
	public boolean equals(Object obj) {
		Human human = (Human) obj;	//id 相同视为同一对象
		return this.id == human.id;
	}
	
	@Override
	public int hashCode() {
		return this.id;
	}
	
}

class Emp implements Comparable{
	int id;
	String name;
	int salary;
	public Emp(int id, String name, int salary) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	
	@Override
	public String toString() {
		return "{ 编号：" + this.id + " 姓名：" + this.name + "薪水：" + this.salary + "}";
	}
	
	@Override	//元素与元素之间的比较规则
	public int compareTo(Object o) {
		Emp emp = (Emp) o;
//		System.out.println(this.name + " ：" + emp.name);	//查看比较过程
		return this.salary - emp.salary;
	}
}


class MyComparator implements Comparator{
	@Override
	public int compare(Object o1, Object o2) {
		Emp e1 = (Emp) o1;
		Emp e2 = (Emp) o2;
		return e1.id - e2.id;
	}
}

public class LearnSet {

	public static void main(String[] args) {
//		set();
//		hashSet();
		treeSet();
	}
	
	//简单演示 set 方法
	public static void set() {
		Set set = new HashSet();
		set.add("张三");
		set.add("李四");
		set.add("王五");
		System.out.println(set.add("王五"));	//不可重复
		
		System.out.println(set);	//出来无序
	}
	
	//演示 HashSet 方法
	public static void hashSet() {
		 HashSet<Human> hashSet = new HashSet<Human>();
		 hashSet.add(new Human(110, "张三"));
		 hashSet.add(new Human(220, "李四"));
		 hashSet.add(new Human(330, "王五"));
		 hashSet.add(new Human(110, "赵六"));
		 
		 System.out.println(hashSet);
	}
	
	public static void treeSet() {
		TreeSet treeSet = new TreeSet();
//		treeSet.add(10);
//		treeSet.add(1);
//		treeSet.add(4);
//		treeSet.add(2);
		
		treeSet.add("abc");
		treeSet.add("study");
		treeSet.add("day");
		
		System.out.println(treeSet);
		
		//添加不具备自然顺序特性的元素时，需要实现 Comparable 的 CompareTo 方法
		TreeSet<Emp> emps = new TreeSet<Emp>();
		emps.add(new Emp(110, "张三", 2000000));
		emps.add(new Emp(120, "李四", 1000000));
		emps.add(new Emp(130, "王五", 300000));
		
		System.out.println(emps);
		
		
		//添加不具备自然顺序特性的元素时，需要实现 Comparable 的 CompareTo 方法
		MyComparator comparator = new MyComparator();
		TreeSet<Emp> emps1 = new TreeSet<Emp>(comparator);
		emps1.add(new Emp(110, "张三", 1000000));
		emps1.add(new Emp(120, "李四", 2000000));
		emps1.add(new Emp(130, "王五", 3000000));
		
		System.out.println(emps1);
		
	}

}
